use serde::{ Deserialize, Serialize };
use ts_rs::TS;

use super::IndicatorActionWrap;

/// When source value goes above the upper bound, then returns full buy signal.
/// When source value goes under the lower bound, then returns full sell signal.
/// Otherwise returns signal according to relative position of the source value based on upper bound and lower bound values.
///
/// Struct yata::indicators::BollingerBands
///
/// 参见[BOLL](https://docs.rs/yata/latest/yata/indicators/struct.BollingerBands.html)
///
#[derive(Debug, Serialize, Deserialize, Default, TS, Clone)]
#[ts(export)]
pub struct BOLL {
    /// Every `Indicator` proceed an input of [`OHLCV`](crate::core::OHLCV) and returns an `IndicatorResult`
    /// which consist of some returned raw values and some calculated signals.
    ///
    /// `Indicator` may return up to 4 signals and 4 raw values at each step
    /// 1 digital signal
    /// When source value goes above the upper bound, then returns full buy signal.
    /// When source value goes under the lower bound, then returns full sell signal.
    /// Otherwise returns signal according to relative position of the source value based on upper bound and lower bound values.
    pub signal0: Option<IndicatorActionWrap>,

    /// upper bound
    pub upper: f64,

    /// middle value, using BBI value: BBI（Bullish Bearish Indicator，多空线）
    pub middle: f64,

    /// lower bound
    pub lower: f64,
}

/// Configuration for the BOLL Bollinger Bands
#[derive(Serialize, Deserialize, Debug, TS, Clone, Copy)]
#[ts(export)]
pub struct BOLLConfig {
    /// Main period length. Default is 20
    /// Range in [3; PeriodType::MAX)
    pub avg_size: u8,
    /// Standard deviation multiplier for bounds. Default is 2.0
    /// Range in (0.0; +inf)
    pub sigma: f64,
    // source: Source
    // Source type of values. Default is Close
}

impl Default for BOLLConfig {
    fn default() -> Self {
        BOLLConfig {
            avg_size: 20,
            sigma: 2.0,
        }
    }
}
